package nl.zuiderfestival.raydance.view.canvas;

import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Point2D;

import javax.swing.JComponent;

public class ZoneDragHandler extends JComponent implements MouseListener, MouseMotionListener {

	private static final long serialVersionUID = 1L;
	
	private ZoneDisplay canvas;
	
	private boolean isDragging;
	private boolean isResizing;
	
	private Point2D mouseDown;
	private Rectangle previousRectangle;
	
	public ZoneDragHandler(ZoneDisplay canvas) {
		super();
		this.canvas = canvas;
		mouseDown = new Point2D.Double(0, 0);
	}

	public void mouseDragged(MouseEvent e) {
		ZoneShape selectedItem = canvas.getSelectedItem();
		
		if (selectedItem != null) {

			double movementX = e.getX() - mouseDown.getX();
			double movementY = e.getY() - mouseDown.getY();
			Dimension size = canvas.getSize();
			Rectangle rect = selectedItem.getRectangle();
			
			if (isDragging) {
				
				double minX = 0;
				double minY = 0;
				double maxX = size.width-rect.width;
				double maxY = size.height-rect.height;
				
				double newX = movementX + previousRectangle.x;
				double newY = movementY + previousRectangle.y;
				
				//breaks MVC
				selectedItem.setLocation(ensureRange(newX, minX, maxX), ensureRange(newY, minY, maxY));
			
			} else if (isResizing) {
				double minWidth = 25;
				double minHeight = 25;
				double maxWidth = size.getWidth() - rect.getX();
				double maxHeight = size.getHeight() - rect.getY();
				
				double newWidth = previousRectangle.width + movementX;
				double newHeight = previousRectangle.height + movementY;
				
				//breaks MVC
				selectedItem.setSize(ensureRange(newWidth, minWidth, maxWidth), ensureRange(newHeight, minHeight, maxHeight));
				
			}
		}
		canvas.repaint();

	}

	private double ensureRange(double value, double min, double max) {
		   return Math.min(Math.max(value, min), max);
	}


	/**
	 * Update the cursor if we're above a shape.
	 */
	public void mouseMoved(MouseEvent e) {
		ZoneShape mouseOverItem = canvas.getShapeAt(e.getPoint());
		if (mouseOverItem != null) {
			if (mouseOverItem.equals(canvas.getSelectedItem())) {
				if (mouseOverItem.isMouseOverResizeThumb(e.getPoint())) {
					canvas.setCursor(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR));
				} else {
					canvas.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
				}
				
			} else {
				canvas.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
			}
		} else {
			canvas.setCursor(Cursor.getDefaultCursor());
		}
	}

	public void mousePressed(MouseEvent e) {
		ZoneShape mouseOverItem = canvas.getShapeAt(e.getPoint());
		if (mouseOverItem != null) {
			if (!mouseOverItem.equals(canvas.getSelectedItem())) {
				canvas.setSelectedItem(mouseOverItem);
				canvas.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
				isDragging = true;
			} else {
				if (mouseOverItem.isMouseOverResizeThumb(e.getPoint())) {
					canvas.setCursor(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR));
					isResizing = true;
				} else {
					canvas.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
					isDragging = true;
				}
			}
			mouseDown.setLocation(e.getX(), e.getY());
			previousRectangle = new Rectangle(canvas.getSelectedItem().getRectangle());
		} else {
			isDragging = false;
			isResizing = false;
		}
	}

	public void mouseReleased(MouseEvent e) {
		canvas.repaint();
		isDragging = false;
	}

	public void mouseClicked(MouseEvent e) { }
	public void mouseEntered(MouseEvent e) { }
	public void mouseExited(MouseEvent e) { }

}
